using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Collections;

namespace Web.Ajax.Controls
{
    [ToolboxData("<{0}:Tree runat=\"server\"></{0}:Tree>")]
    [ControlBuilderAttribute(typeof(TreeBuilder))]
    [ParseChildren(false)]
    public class Tree : AjaxControl
    {
        public Tree()
        {
            Height = new System.Web.UI.WebControls.Unit("500px");
            Width = new System.Web.UI.WebControls.Unit("100%");
			Border = true;
			CssClass = "TreePanel";
			FixedHeight = true;
			Lines = true;
        }

        protected override void OnInit(EventArgs e)
        {
            Ajax.RegisterAjaxMethods(this);
            base.OnInit(e);
            if (PopupTitle != null)
                if (PopupTitle.TitleRight != null)
                    PopupTitle.TitleRight.DisplayClose = false;
            if (Page != null)
            {
				Page.RegisterJavascriptFile(Resources.Javascript.AjaxControl);
				Page.RegisterStyleSheet(Resources.StyleSheets.Tree);
                Page.RegisterJavascriptFile(Resources.Javascript.Tree);
				Page.RegisterJavascriptFile(Resources.Javascript.PopupMenu);
				Page.RegisterStyleSheet(Resources.StyleSheets.PopupMenu);

				Calendar.RegisterResources(Page);
			}
        }

        /// <summary>
        /// The signature for the static method used to return the Tree data.
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public delegate TreeData[] GetDataMethod(TreeInfo TreeInfo);
        public GetDataMethod DataMethod;

        private string[] levelCss;
        public string[] LevelCss
        {
            get { return levelCss; }
            set { levelCss = value; }
        }

        private bool highlightLastTitleClicked;
        public bool HighlightLastTitleClicked
        {
            get { return highlightLastTitleClicked;}
            set { highlightLastTitleClicked= value;}
        }

		public bool FillHeight
		{
			get;
			set;
		}

		public bool BoxSelectedNode
		{
			get;
			set;
		}


		public bool Border
		{
			get;
			set;
		}

		public bool FixedHeight
		{
			get;
			set;
		}

		public bool Lines { get; set; }

        protected override void Render(HtmlTextWriter writer)
        {
            if (DataMethod == null&&!DelayLoading)
                throw new Exception("DataMethod was not set on Tree: " + JavascriptId + ". A DataMethod must be provided for the Tree to work.");
            if (!Visible)
                return;
            StringBuilder html = new StringBuilder();
            string style = "";
            string width = Width.ToString();
            if (width != "100%")
                style += "width:" + width + ";";
			if(FixedHeight)
				style += "height:" + Height.ToString() + ";";
            html.Append("<div class=\""+CssClass+" "+(Border?"TreeBorder":"")+"\" id=\"" + JavascriptId + "\" style=\""+style+"\">");
            html.Append("<div id=\"" + JavascriptId + "_Content\"></div></div>");
            writer.Write(html.ToString());
            writer.WriteLine("<script type=\"text/javascript\">");
			if (DataMethod != null)
				writer.WriteLine("var " + JavascriptId + " = new Tree('" + JavascriptId + "','" + DataMethod.Method.DeclaringType.AssemblyQualifiedName + "','" + DataMethod.Method.Name + "');");
			else
				writer.WriteLine("var " + JavascriptId + " = new Tree('" + JavascriptId + "');");
            RenderProperty(writer, "NoData", NoData);
            RenderProperty(writer, "Browser", Browser.ToString());
            RenderProperty(writer, "HighlightLastTitleClicked", HighlightLastTitleClicked);
			RenderProperty(writer, "BoxSelectedNode", BoxSelectedNode);
			RenderProperty(writer, "Lines", Lines);
			if (LevelCss != null)
                RenderProperty(writer, "LevelCss", LevelCss);
            RenderParameters(writer);
			if (!DelayLoading)
				writer.WriteLine(JavascriptId + ".GetData();");
			if(FillHeight)
				writer.WriteLine(JavascriptId + ".FillHeight();");
            writer.WriteLine("</script>");
        }

        [Ajax]
        public static TreeResponse GetData(TreeRequest request)
        {
            TreeResponse response= new TreeResponse();
            try
            {
				response.Path = request.TreeInfo.Path;
				Type Type = System.Type.GetType(request.DataMethodType);
                if (Type == null)
                    throw new Exception("AjaxTree: Invalid Type.");
                MethodInfo Method = Type.GetMethod(request.DataMethodName);
                if (request.TreeInfo.Parameters == null)
                    request.TreeInfo.Parameters = new Parameter[0];
                object o = null;
                o = Method.Invoke(null, new object[] { request.TreeInfo });
                if (o == null || !(o is TreeData[]))		
                    throw new Exception("Tree: Data Method did not return a TreeData[].");
                response.Data = (TreeData[])o;
                response.OnComplete = request.TreeInfo.OnComplete;
            }
            catch (Exception e)
            {
                Logging.Log.Error(e);
                if (e.InnerException != null)
                    response.Message = e.InnerException.Message;
                else
                    response.Message = e.Message;
            }
            return response;
        }
    }

    #region TreeBuilder
    /// <summary>
    /// The Control Builder for the AjaxGrid class.
    /// </summary>
    internal class TreeBuilder : ControlBuilder
    {
        public override System.Type GetChildControlType(string tagName, System.Collections.IDictionary attribs)
        {
            tagName = tagName.ToLower();
            if (tagName == "parameter")
                return typeof(Parameter);
            return null;
        }
    }
    #endregion


    public class TreeInfo : ControlInfo
    {
        public string Path;
        public TreeData[] Data;
    }

    public class TreeData : IComparable
    {
        public string Id;
        public string Title;
        public string TitleWidth;
        public string Data;
        public string DataWidth;
        public int Min;
        public int Max;
        public bool Collapse;
        public bool Selected;
        public bool Selectable;
        public bool CurrentTitle;
        public bool Ajax;
        public string OnTitleClick;
		public string OnDblClick;
        public string Resource;
        public TreeData[] Children;
        public string LinkSectionWidth;
        public Link[] Links;
        public string[] Info;
		public Options Options;
		public Hashtable Attributes;
		public string Css;
		public string ContentCss;
		public int Order = int.MaxValue;

		public int CompareTo(object o)
		{
			var td = (TreeData)o;
			if (td == null)
				return -1;
			return Order.CompareTo(td.Order);
		}
    }

    public class Link
    {
        public string Text;
        public string OnClick;
        public string Url;

        public Link()
        {
        }

        public Link(string Text,string OnClick)
        {
            this.Text = Text;
            this.OnClick = OnClick;
        }

        public Link(string Text, string OnClick, string Url)
        {
            this.Text = Text;
            this.OnClick = OnClick;
            this.Url = Url;
        }
    }

    public class TreeRequest : AjaxControlRequest
    {
        public TreeInfo TreeInfo;
    }

    public class TreeResponse : AjaxControlResponse
    {
        public string Path;
        public TreeData[] Data;
    }
}
